/*
 * http_client_pool.h
 *
 *  Created on: 2013-6-12
 *      Author: joelwzli
 */

#ifndef HTTP_CLIENT_POOL_H_
#define HTTP_CLIENT_POOL_H_

#include <list>
#include <string>
#include "c2cplatform/library/basic/singleton_t.h"
#include "http_client_factory.h"
#include "intf_http_client.h"

namespace comm
{
namespace http
{
namespace custorm
{
class IHttpClient;
class CHttpClientFactory;
class CHttpClientPool
{
  public:
    CHttpClientPool()
        : m_dwCapacity(0)
    {
    }

    virtual ~CHttpClientPool()
    {
        ForceCleanUp();
        m_dwCapacity = 0;
    }

    /**
     * @see IHttpClientPool::Initialize
     */
    virtual uint32_t Initialize(uint32_t dwCapacity)
    {
        if (m_dwCapacity < 1)
        {
            char pstBuf[64];
            snprintf(pstBuf, sizeof(pstBuf), "Capacity of http client is too small: %d", m_dwCapacity);
            m_sErrMsg = m_dwCapacity;
            return 1;
        }

        m_dwCapacity = dwCapacity;
        for (uint32_t i = 0; i < m_dwCapacity; i++)
        {
            IHttpClient *pHttpClient = m_oClientFactory.CreateHttpClient();
            if (NULL != pHttpClient)
            {
                m_oClientList.push_back(pHttpClient);
            }
            else
            {
                while (m_oClientList.size() > 0)
                {
                    pHttpClient = m_oClientList.back();
                    delete pHttpClient;
                    m_oClientList.pop_back();
                }
                return 2;
            }
        }
        return 0;
    }

    /**
     * @see IHttpClientPool::GetHttpClient
     */
    virtual IHttpClient* GetHttpClient(void)
    {
        if (m_oClientList.size() != 0)
        {
            IHttpClient *pClient = m_oClientList.back();
            m_oClientList.pop_back();
            return pClient;
        }
        else
        {
            IHttpClient *pClient = m_oClientFactory.CreateHttpClient();
            if (NULL == pClient)
            {
                m_sErrMsg = m_oClientFactory.GetLastError();
                return NULL;
            }
            return pClient;
        }
    }

    /**
     * @see IHttpClientPool::ReclaimHttpClient
     */
    virtual void ReclaimHttpClient(IHttpClient *pClient)
    {
        if (pClient != NULL)
        {
            if (m_oClientList.size() > m_dwCapacity)
            {
                delete pClient;
            }
            else
            {
                m_oClientList.push_back(pClient);
            }
        }
    }

    /**
     * @see IHttpClientPool::GetLastError
     */
    virtual const std::string& GetLastError(void) const
    {
        return m_sErrMsg;
    }

    /**
     * @see IHttpClientPool::GetSize
     */
    virtual uint32_t GetSize() const
    {
        return m_oClientList.size();
    }

    /**
     * @see IHttpClientPool::GetCapacity
     */
    virtual uint32_t GetCapacity() const
    {
        return m_dwCapacity;
    }

    /**
     * @see IHttpClientPool::ForceCleanUp
     */
    virtual void ForceCleanUp()
    {
        IHttpClient *pHttpClient = NULL;
        while (m_oClientList.size() > 0)
        {
            pHttpClient = m_oClientList.back();
            delete pHttpClient;
            m_oClientList.pop_back();
        }
    }

  private:
    std::string m_sErrMsg;
    uint32_t m_dwCapacity;
    CHttpClientFactory m_oClientFactory;
    std::list<IHttpClient*> m_oClientList;
};

}
}
}

////////////////////////////// Declare Singleton ////////////////////////////////
typedef CSingletonT<comm::http::custorm::CHttpClientPool, CDummyLock> CHttpClientPoolSingleton;
#define CHTTP_CLIENT_POOL CHttpClientPoolSingleton::Instance()

/////////////////////////////////////////////////////////////////////////////////

#endif /* HTTP_CLIENT_POOL_H_ */

